﻿#include "FileDirList.h"
#include "mycrc.h"
#include <QApplication>
#include <QWidget>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QDebug>

FileDirList::FileDirList(void)
{
    QFont font("微软雅黑", 12);
    tab.resize(750, 630);
    tab.setFont(font);
    //设置列数
    tab.setColumnCount(6);
    //表头标题用QStringList来表示
    QStringList headerText;
    headerText << "名称" << "地址偏移" << "大小" << "CRC" << "宽" << "高";
    tab.setHorizontalHeaderLabels(headerText);
    tab.setEditTriggers(QAbstractItemView::NoEditTriggers); //不允许编辑
    //设置列宽
    tab.setColumnWidth(0, 300);
    tab.setColumnWidth(1, 108);
    tab.setColumnWidth(2, 108);
    tab.setColumnWidth(3, 114);
    tab.setColumnWidth(4, 45);
    tab.setColumnWidth(5, 45);
    pinfo = new file_dir_info[100];
    info_tal = 100;
    connect(this, SIGNAL(show_signal(int)), this, SLOT(show_slost(int)));
    reset();
}

FileDirList::~FileDirList()
{
    delete [] pinfo;
    pinfo = NULL;
    info_tal = 0;
}

void FileDirList::set(QWidget *parent, int x, int y)
{
    tab.setParent(parent);     // 设置父窗口
    tab.move(x, y);
}

void FileDirList::reset(void)
{
    memset(pinfo, 0, sizeof(file_dir_info)*info_tal);
    file_offset = 0;
    info_cnt = 0;
    add_offset = 1024;
    tab.setRowCount(0);
    tab.clearContents();
}

void FileDirList::set_path(QString in_path)
{
    int cnt_bak = get_count();
    // 使用 QFileInfo 来解析路径
    QFileInfo fileInfo(in_path);
    // 提取路径部分
    QString path = fileInfo.absolutePath();
    QDir dir(path);  // 替换为你要遍历的目录路径
    // 获取目录中的文件列表
    QStringList fileList = dir.entryList(QDir::Files);

    foreach (QString file, fileList)
    {
        file_add(path, file);
    }

    if (cnt_bak != get_count())
    {
        emit updata(get_count());  // 文件数发送变化发射信号
    }
}

void FileDirList::set_offset(unsigned short offset)
{
    if (add_offset != offset)
    {
        add_offset = offset;

        for (int i = 0; i < info_cnt; i++)
        {
            emit show_signal(i);  // 发射信号
        }
    }
}

unsigned short FileDirList::get_offset(void)
{
    return add_offset;
}

int FileDirList::get_count(void)
{
    return info_cnt;
}

const file_dir_info *FileDirList::get_index(int index)
{
    if (index < info_cnt)
    {
        return &pinfo[index];
    }

    return NULL;
}

int FileDirList::file_add(QString path, QString file)
{
    QByteArray Arrayfile = file.toUtf8();
    const char *cfile = Arrayfile.data();
    int len = strlen(cfile);

    for (int i = 0; (i < FILE_DIR_NAME_SIZE) && (i < len); i++)
    {
        if ((cfile[i] < 0x20) || (cfile[i] > 0x7E))
        {
            return -1;
        }
    }

    if (info_cnt >= info_tal)
    {
        file_dir_info *p_new = new file_dir_info[info_tal + 50];
        memset(p_new, 0, sizeof(file_dir_info) * (info_tal + 50));
        memcpy(p_new, pinfo, sizeof(file_dir_info)*info_tal);
        delete [] pinfo;
        pinfo = p_new;
        info_tal += 50;
    }

    int size = get_file_size(path, file);

    if (size)
    {
        file_dir_info *p_info = &pinfo[info_cnt];
        QByteArray Arraypath = path.toUtf8();
        const char *cpath = Arraypath.data();
        memcpy(p_info->path, cpath, (strlen(cpath) < (FILE_DIR_PATH_SIZE - 1)) ? strlen(cpath) : (FILE_DIR_PATH_SIZE - 1));
        memcpy(p_info->name, cfile, (strlen(cfile) < (FILE_DIR_NAME_SIZE - 1)) ? strlen(cfile) : (FILE_DIR_NAME_SIZE - 1));
        p_info->adder = file_offset;
        p_info->size = size;
        p_info->crc = file_crc(path, file);
        p_info->w = 0;
        p_info->h = 0;

        if (pic_ok)
        {
            p_info->w = std::abs(pic.Width());
            p_info->h = std::abs(pic.Height());
            pic_ok = false;
        }

        file_offset += ((size + 0x1F) & 0x0FFFFFFE0); /* 32byte */
        emit show_signal(info_cnt++);  // 发射信号
        return 0;
    }

    return -2;
}

int FileDirList::get_file_size(QString path, QString file)
{
    int size = 0;
    QDir dir(path);
    QString fullPath = dir.filePath(file);
    QFileInfo fileInfo(fullPath);

    if (fileInfo.exists() && fileInfo.isFile())// 检查文件是否存在
    {
        // 获取文件大小（以字节为单位）
        size = fileInfo.size();
    }

    return size;
}

unsigned long FileDirList::file_crc(QString qstrpath, QString qstrfile)
{
    unsigned long  crc = 0;
    QDir dir(qstrpath);
    QString fullPath = dir.filePath(qstrfile);
    // 创建 QFile 对象并打开二进制文件
    QFile file(fullPath);

    if (!file.open(QIODevice::ReadOnly))
    {
        qDebug() << "Could not open file for reading";
        return crc;
    }

    qDebug() << "FileDirList::file_crc" << qstrfile;
    // 读取文件内容
    QByteArray data = file.readAll();
    unsigned long size = file.size();
    // 关闭文件
    file.close();
    mycrc crc32;
    crc32.push(data.constData(), size);
    crc = crc32.value32();
    pic_ok = pic.push(data.constData(), size);
    return crc;
}

void FileDirList::show_slost(int index)
{
    if (index < info_cnt)
    {
        qDebug() << "show" << index << pinfo[index].name << pinfo[index].adder << pinfo[index].size;
        tab.setRowCount(index + 1); //设置行数
        tab.setItem(index, 0, new QTableWidgetItem(QString::fromUtf8(pinfo[index].name)));
        tab.setItem(index, 1, new QTableWidgetItem(QString("0x%1").arg(pinfo[index].adder + add_offset, 6, 16, QChar('0')).toUpper()));
        tab.setItem(index, 2, new QTableWidgetItem(QString("0x%1").arg(pinfo[index].size, 6, 16, QChar('0')).toUpper()));
        tab.setItem(index, 3, new QTableWidgetItem(QString("0x%1").arg(pinfo[index].crc, 8, 16, QChar('0')).toUpper()));
        tab.setItem(index, 4, new QTableWidgetItem(QString::number(pinfo[index].w, 10).toUpper()));
        tab.setItem(index, 5, new QTableWidgetItem(QString::number(pinfo[index].h, 10).toUpper()));
    }
}
